package com.example.wechat.login.aspect;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * 分布式锁切面
 */
@Aspect
@Component
public class DistributedLockAspect {

    @Resource
    private RedissonClient redissonClient;

    @Around("@annotation(com.example.wechat.login.annotation.DistributedLock)")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取用户 ID
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        String userId = (String) authentication.getPrincipal();
        // 锁的键包含方法名和用户 ID
        String lockKey = "distributed:lock:" + joinPoint.getSignature().getName() + ":" + userId;
        RLock lock = redissonClient.getLock(lockKey);
        try {
            // 尝试加锁，最多等待 5 秒，锁自动释放时间为 10 秒
            if (lock.tryLock(5, 10, TimeUnit.SECONDS)) {
                return joinPoint.proceed();
            } else {
                throw new RuntimeException("获取分布式锁失败");
            }
        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                lock.unlock();
            }
        }
    }
}